using System;
using System.Collections.Generic;
using System.Text;

namespace UGent.Tsp
{
    public class BruteForceSwapper : ISwapper
    {
        #region Constructors
        public BruteForceSwapper(Route route)
            : this(route, 0)
        {
        }

        public BruteForceSwapper(Route route, int count)
        {
            this.route = route;
            this.count = route.Map.CityCount;
            this.permutations = new PermutationIterator(this.count);
        }
        #endregion

        #region Properties
        private int proposed;
        private int accepted;
        private int count;
        private int[] current;
        private PermutationIterator permutations;

        public int ProposedMoves
        {
            get { return proposed; }
        }

        public int AcceptedMoves
        {
            get { return accepted; }
        }

        private Route route;
        public IRoute Route
        {
            get { return route; }
        }

        public int Count
        {
            get
            {
                return count;
            }
        }
        #endregion

        #region Methods
        public void Generate()
        {
            if (!permutations.MoveNext())
            {
                permutations.Reset();
                permutations.MoveNext();
            }

            current = permutations.Current;

            proposed++;
        }

        public void Do()
        {
            for (int i = 0; i < count; i++)
                route[i] = current[i];

            accepted++;
        }

        public double GetDelta()
        {
            double delta = 0;

            int j;
            for (int i = 0; i < count; i++)
            {
                if (i != count - 1)
                    j = i + 1;
                else
                    j = 0;

                if (route[i] != current[i] || route[j] != current[j])
                {
                    delta -= route.GetDistance(i, j);
                    delta += route.Map.GetDistance(current[i], current[j]);
                }
            }

            return delta;
        }
        #endregion
    }
}
